import http, {buildUrl} from '@/helpers/http'
import {
  ICollectionResponse,
  ILoadOptions,
  PaginatedCollection,
} from './interfaces'

/**
 *
 * Used to load a collection of resources
 * @param url
 * @param options
 * @returns A collection or a paginated collection with the pagination related informations
 */
export async function loadCollection(
  url: string,
  options: ILoadOptions = {
    fields: [],
    related: [],
    pageOptions: null,
    filters: {},
  }
): Promise<PaginatedCollection | ICollectionResponse> {
  const { fields, related, pageOptions, filters } = options
  let params = []
  if (fields) {
    params = params.concat(fields.map((name) => ['fields', name]))
  }
  if (related) {
    params = params.concat(related.map((name) => ['related', name]))
  }
  if (pageOptions) {
    params = params.concat(Object.entries(pageOptions))
  }
  if (filters) {
    params = params.concat(
      Object.entries(filters).map(([key, value]) => {
        key = 'filter_' + key
        return [key, value]
      })
    )
  }
  const reqParams = new URLSearchParams(params)
  const callUrl = `${url}?${reqParams}`
  return http.get(callUrl)
}

export class BaseApiService {
  baseItemUrl: string
  collectionUrl: string
  constructor(baseItemUrl: string) {
    this.baseItemUrl = baseItemUrl
    this.collectionUrl = baseItemUrl
  }
  setCollectionUrl(collectionUrl: string) {
    this.collectionUrl = collectionUrl
  }
  getItemUrl(id: string): string {
    return `${this.baseItemUrl}/${id}`
  }
}
export class ReadOnlyApiService extends BaseApiService {
  async load(id: string, fields) : Promise<any> {
    const itemBaseUrl = this.getItemUrl(id)
    let url
    if (fields) {
      url = buildUrl(itemBaseUrl, fields.map(x => ['fields', x]))
    } else {
      url = itemBaseUrl
    }
    return http.get(url)
  }
}
export class ModelApiService extends ReadOnlyApiService {
  async create(data: any, url: String): Promise<any> {
    if (!url) {
      url = this.collectionUrl
      if (!url) {
        throw new Error("Can't add : Collection url not set")
      }
    }
    return http.post(url, data)
  }
  async update(data: any, id: number = null): Promise<any> {
    id = id || data.id
    if (id === null) {
      throw new Error("Can't update : Id not set")
    }
    const url = this.getItemUrl(id)
    return http.put(url, data)
  }
  async patch(id: string, patch: any): Promise<any> {
    const url = this.getItemUrl(id)
    return http.patch(url, patch)
  }
  async delete(id: string): Promise<any> {
    const url = this.getItemUrl(id)
    return http.delete(url)
  }
  async save(data: Object, item?: Object): Promise<any> {
    if (item.id) {
      return this.update(data, item.id)
    } else {
      return this.create(data)
    }
  }
}
